#include <cstdint>
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>

/**
 * Luogu P1342: Invitation
 * This problem shows one application of reversed graph.
 */

struct Edge {
    int to;
    uint64_t dist;

    Edge(int to, uint64_t dist) : to(to), dist(dist) {}
};

struct Vertex {
    int index;
    std::vector<Edge> forw, rev;
    uint64_t dist;

    Vertex(int idx) : index(idx) {}
};

std::vector<Vertex> vertices;

struct DistCmp {
    bool operator()(Vertex *u, Vertex *v) const { return u->dist > v->dist; }
};

template <class F>
void shortestPath(F getEdge) {
    // Initialization
    for (auto &v : vertices) v.dist = UINT64_MAX;
    vertices[0].dist = 0;
    std::priority_queue<Vertex *, std::vector<Vertex *>, DistCmp> heap;
    heap.push(&vertices[0]);
    std::vector<bool> visited(vertices.size(), false);

    // Run Dijkstra algorithm
    while (!heap.empty()) {
        Vertex *u = heap.top();
        heap.pop();
        for (Edge &e : getEdge(u)) {
            Vertex *v = &vertices[e.to];
            uint64_t newDist = u->dist + e.dist;
            if (newDist < v->dist) {
                v->dist = newDist;
                heap.push(v);
            }
        }
    }
}

int main() {
    // Input
    int nVerts, nEdges;
    scanf("%d %d", &nVerts, &nEdges);
    for (int i = 0; i < nVerts; i++) vertices.emplace_back(i);
    for (int i = 0; i < nEdges; i++) {
        int from, to;
        uint64_t dist;
        scanf("%d %d %lld", &from, &to, &dist);
        from--, to--;
        vertices[from].forw.emplace_back(to, dist);
        vertices[to].rev.emplace_back(from, dist);
    }

    // Run shortest path forward and backward
    uint64_t cost = 0;
    shortestPath([](Vertex *v) -> std::vector<Edge> & { return v->forw; });
    for (auto &v : vertices) cost += v.dist;
    shortestPath([](Vertex *v) -> std::vector<Edge> & { return v->rev; });
    for (auto &v : vertices) cost += v.dist;
    printf("%lld\n", cost);

    return 0;
}